package common.wx;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStreamReader;
import java.io.UnsupportedEncodingException;
import java.security.KeyStore;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Random;
import java.util.Set;
import java.util.UUID;

import javax.net.ssl.SSLContext;

import org.apache.commons.codec.digest.DigestUtils;
import org.apache.commons.lang.StringUtils;
import org.apache.http.HttpEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.conn.ssl.SSLContexts;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.protocol.HTTP;
import org.apache.http.util.EntityUtils;
import org.apache.struts2.ServletActionContext;

import common.impl.DataHandleImpl;
import common.impl.MicroBlog;
import common.impl.MyDateHandleImpl;

public class WxApi {
	private static final String CERT = "/assets/apiclient_cert.p12";
	private final static String wx_key = "20170712159349831321387658cloud_ifw";
	private final static String wx_mch_id = "1332029301";
	private final static String wx_appid = "wx374fb00e61ebac00";
	private final static String wx_client_ip = "121.42.160.187";
	private final static String wx_base_url = "https://api.mch.weixin.qq.com/mmpaymkttransfers/sendredpack";

	public static Map<String, String> sendRedBag(String openId,
			String sendName, String wishing, String reward, String actName,
			String remark) {
		Map<String, String> params = new HashMap<String, String>();
		params.put("nonce_str", getRandomNonce_str());
		params.put("mch_billno", getRandomMch_billno());
		params.put("mch_id", wx_mch_id);
		params.put("wxappid", wx_appid);
		params.put("send_name", sendName);
		params.put("re_openid", openId);
		params.put("total_amount", reward);
		params.put("total_num", "1");
		params.put("wishing", wishing);
		params.put("client_ip", wx_client_ip);
		params.put("act_name", actName);
		params.put("remark", remark);
		String ps = createLinkString(params);
		String sign = getParams(ps);
		// xml
		String xml = "<xml>";
		Set<String> keyS = params.keySet();
		for (Iterator<String> iterator = keyS.iterator(); iterator.hasNext();) {
			String v = iterator.next();
			xml += "<" + v + ">" + params.get(v) + "</" + v + ">";
		}
		xml += "<sign>" + sign + "</sign>";
		xml += "</xml>";
		String serverUrl = ServletActionContext.getServletContext()
				.getRealPath("/");
		FileInputStream instream = null;
		CloseableHttpClient httpclient = null;
		CloseableHttpResponse response = null;
		Map<String, String> result_map = null;
		try {
			instream = new FileInputStream(new File(serverUrl + CERT));
			// 指定读取证书格式为PKCS12
			// 读取本机存放的PKCS12证书文件
			// 指定PKCS12的密码(商户ID)
			KeyStore keyStore = KeyStore.getInstance("PKCS12");
			keyStore.load(instream, wx_mch_id.toCharArray());
			SSLContext sslcontext = SSLContexts.custom().loadKeyMaterial(
					keyStore, wx_mch_id.toCharArray()).build();
			// 指定TLS版本
			SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(
					sslcontext,
					new String[] { "TLSv1" },
					null,
					SSLConnectionSocketFactory.BROWSER_COMPATIBLE_HOSTNAME_VERIFIER);
			// 设置httpclient的SSLSocketFactory
			httpclient = HttpClients.custom().setSSLSocketFactory(sslsf)
					.build();
			HttpPost httpost = new HttpPost(wx_base_url);
			StringEntity se = new StringEntity(xml, HTTP.UTF_8);
			httpost.setEntity(se);
			response = httpclient.execute(httpost);
			HttpEntity entity = response.getEntity();
			if (entity != null) {
				BufferedReader bufferedReader = new BufferedReader(
						new InputStreamReader(entity.getContent(), "utf-8"));
				String text = "";
				String text_temp;
				while ((text_temp = bufferedReader.readLine()) != null) {
					text += text_temp;
				}
				result_map = DataHandleImpl.xmlToMap(text);
			}
			EntityUtils.consume(entity);
		} catch (Exception e) {
		} finally {
			if (null != instream)
				try {
					instream.close();
				} catch (Exception e2) {
				}
			if (null != httpclient)
				try {
					httpclient.close();
				} catch (Exception e2) {
				}
			if (null != response)
				try {
					response.close();
				} catch (Exception e2) {
				}
		}
		return result_map;

	}

	private static String getRandomNonce_str() {
		String response = new MyDateHandleImpl().getCurrentDateString();
		Random random = new Random();
		int a = random.nextInt(10000);
		response += "-" + a;
		return response;
	}

	private static String getRandomMch_billno() {
		String response = wx_mch_id
				+ new MyDateHandleImpl().getCurrentDateString();
		Random random = new Random();
		int a = random.nextInt(1000000000);
		response += a;
		return response;
	}

	/**
	 * 把数组所有元素排序，并按照“参数=参数值”的模式用“&”字符拼接成字符串
	 * 
	 * @param params
	 *            需要排序并参与字符拼接的参数组
	 * @return 拼接后字符串
	 */
	private static String createLinkString(Map<String, String> params) {
		List<String> keys = new ArrayList<String>(params.keySet());
		Collections.sort(keys);
		String prestr = "";
		for (int i = 0; i < keys.size(); i++) {
			String key = keys.get(i);
			String value = params.get(key);
			if (i == keys.size() - 1) {// 拼接时，不包括最后一个&字符
				prestr = prestr + key + "=" + value;
			} else {
				prestr = prestr + key + "=" + value + "&";
			}
		}
		return prestr;
	}

	private static String getParams(String ps) {
		try {
			String url = ps;
			url += "&key=" + wx_key;
			String md5_sign = sign(url, "utf-8").toUpperCase();
			url += "&sign=" + md5_sign;
			System.out.println(md5_sign);
			return md5_sign;
		} catch (Exception e) {
		}
		return null;
	}

	public static String sign(String text, String input_charset) {
		return DigestUtils.md5Hex(getContentBytes(text, input_charset));
	}

	private static byte[] getContentBytes(String content, String charset) {
		if (charset == null || "".equals(charset)) {
			return content.getBytes();
		}
		try {
			return content.getBytes(charset);
		} catch (UnsupportedEncodingException e) {
			throw new RuntimeException("MD5签名过程中出现错误,指定的编码集不对,您目前指定的编码集是:"
					+ charset);
		}
	}

	/**
	 * 刷卡支付
	 * 
	 * @param body
	 * @param detail
	 * @param out_trade_no
	 * @param total_fee
	 * @param auth_code
	 * @return
	 */
	public static String shuaka(String body, String detail,
			String out_trade_no, String total_fee, String auth_code) {
		Map<String, String> params = new HashMap<String, String>();
		params.put("appid", WxConfig.wx_appid);
		params.put("mch_id", WxConfig.wx_mch_id);
		String nonce_str = UUID.randomUUID().toString().replaceAll("-", "");
		params.put("nonce_str", nonce_str);
		params.put("body", body);
		params.put("detail", detail);
		params.put("out_trade_no", out_trade_no);
		params.put("total_fee", total_fee);
		params.put("fee_type", "CNY");
		params.put("spbill_create_ip", WxConfig.wx_client_ip);
		params.put("auth_code", auth_code);
		String sign = MicroBlog.sign(params, WxConfig.wx_key);
		String xml = "<xml>";
		Set<String> keyS = params.keySet();
		for (Iterator<String> iterator = keyS.iterator(); iterator.hasNext();) {
			String v = iterator.next();
			xml += "<" + v + ">" + params.get(v) + "</" + v + ">";
		}
		xml += "<sign>" + sign + "</sign>";
		xml += "</xml>";
		return MicroBlog.postHttps(WxConfig.url_shuaka_micropay, xml, null,
				null);
	}

	/**
	 * 刷卡支付-查询订单
	 * 
	 * @param body
	 * @param detail
	 * @param out_trade_no
	 * @param total_fee
	 * @param auth_code
	 * @return
	 */
	public static String shuaka_find(String out_trade_no) {
		Map<String, String> params = new HashMap<String, String>();
		params.put("appid", WxConfig.wx_appid);
		params.put("mch_id", WxConfig.wx_mch_id);
		String nonce_str = UUID.randomUUID().toString().replaceAll("-", "");
		params.put("nonce_str", nonce_str);
		params.put("out_trade_no", out_trade_no);
		String sign = MicroBlog.sign(params, WxConfig.wx_key);
		String xml = "<xml>";
		Set<String> keyS = params.keySet();
		for (Iterator<String> iterator = keyS.iterator(); iterator.hasNext();) {
			String v = iterator.next();
			xml += "<" + v + ">" + params.get(v) + "</" + v + ">";
		}
		xml += "<sign>" + sign + "</sign>";
		xml += "</xml>";
		return MicroBlog.postHttps(WxConfig.url_shuaka_orderquery, xml, null,
				null);
	}

	/**
	 * 公众号付款-下单
	 * 
	 * @param body
	 * @param detail
	 * @param attach
	 * @param out_trade_no
	 * @param total_fee
	 * @param time_start
	 * @param time_expire
	 * @param goods_tag
	 * @param product_id
	 * @param openid
	 * @return
	 */
	public static String addOrderJsApi(String body, String detail,
			String attach, String out_trade_no, String total_fee,
			String time_start, String time_expire, String openid) {
		Map<String, String> params = new HashMap<String, String>();
		params.put("appid", WxConfig.wx_appid);
		params.put("mch_id", WxConfig.wx_mch_id);
		String nonce_str = UUID.randomUUID().toString().replaceAll("-", "");
		params.put("nonce_str", nonce_str);
		params.put("body", body);
		params.put("detail", detail);
		params.put("attach", attach);
		params.put("out_trade_no", out_trade_no);
		params.put("fee_type", "CNY");
		params.put("total_fee", total_fee);
		params.put("spbill_create_ip", WxConfig.wx_client_ip);
		params.put("time_start", time_start);
		params.put("time_expire", time_expire);
		params.put("notify_url", WxConfig.url_notify_pujing);
		params.put("trade_type", WxConfig.trade_type_jsapi);
		params.put("openid", openid);
		String sign = MicroBlog.sign(params, WxConfig.wx_key);
		String xml = "<xml>";
		Set<String> keyS = params.keySet();
		for (Iterator<String> iterator = keyS.iterator(); iterator.hasNext();) {
			String v = iterator.next();
			xml += "<" + v + ">" + params.get(v) + "</" + v + ">";
		}
		xml += "<sign>" + sign + "</sign>";
		xml += "</xml>";
		return MicroBlog.postHttps(WxConfig.url_unifiedorder, xml, null, null);
	}

	public static String addOrderJsApi_yao_shai_zi(String body, String detail,
			String attach, String out_trade_no, String total_fee,
			String time_start, String time_expire, String openid) {
		Map<String, String> params = new HashMap<String, String>();
		params.put("appid", WxConfig.wx_appid);
		params.put("mch_id", WxConfig.wx_mch_id);
		String nonce_str = UUID.randomUUID().toString().replaceAll("-", "");
		params.put("nonce_str", nonce_str);
		params.put("body", body);
		params.put("detail", detail);
		params.put("attach", attach);
		params.put("out_trade_no", out_trade_no);
		params.put("fee_type", "CNY");
		params.put("total_fee", total_fee);
		params.put("spbill_create_ip", WxConfig.wx_client_ip);
		params.put("time_start", time_start);
		params.put("time_expire", time_expire);
		params.put("notify_url", WxConfig.url_notify_yaoshaizi);
		params.put("trade_type", WxConfig.trade_type_jsapi);
		params.put("openid", openid);
		String sign = MicroBlog.sign(params, WxConfig.wx_key);
		String xml = "<xml>";
		Set<String> keyS = params.keySet();
		for (Iterator<String> iterator = keyS.iterator(); iterator.hasNext();) {
			String v = iterator.next();
			xml += "<" + v + ">" + params.get(v) + "</" + v + ">";
		}
		xml += "<sign>" + sign + "</sign>";
		xml += "</xml>";
		return MicroBlog.postHttps(WxConfig.url_unifiedorder, xml, null, null);
	}

	public static String addOrderJsApi_lao_hu_ji(String body, String detail,
			String attach, String out_trade_no, String total_fee,
			String time_start, String time_expire, String openid) {
		Map<String, String> params = new HashMap<String, String>();
		params.put("appid", WxConfig.wx_appid);
		params.put("mch_id", WxConfig.wx_mch_id);
		String nonce_str = UUID.randomUUID().toString().replaceAll("-", "");
		params.put("nonce_str", nonce_str);
		params.put("body", body);
		params.put("detail", detail);
		params.put("attach", attach);
		params.put("out_trade_no", out_trade_no);
		params.put("fee_type", "CNY");
		params.put("total_fee", total_fee);
		params.put("spbill_create_ip", WxConfig.wx_client_ip);
		params.put("time_start", time_start);
		params.put("time_expire", time_expire);
		params.put("notify_url", WxConfig.url_notify_laohuji);
		params.put("trade_type", WxConfig.trade_type_jsapi);
		params.put("openid", openid);
		String sign = MicroBlog.sign(params, WxConfig.wx_key);
		String xml = "<xml>";
		Set<String> keyS = params.keySet();
		for (Iterator<String> iterator = keyS.iterator(); iterator.hasNext();) {
			String v = iterator.next();
			xml += "<" + v + ">" + params.get(v) + "</" + v + ">";
		}
		xml += "<sign>" + sign + "</sign>";
		xml += "</xml>";
		return MicroBlog.postHttps(WxConfig.url_unifiedorder, xml, null, null);
	}
	
	public static String addOrderJsApi_zha_jin_hua(String body, String detail,
			String attach, String out_trade_no, String total_fee,
			String time_start, String time_expire, String openid) {
		Map<String, String> params = new HashMap<String, String>();
		params.put("appid", WxConfig.wx_appid);
		params.put("mch_id", WxConfig.wx_mch_id);
		String nonce_str = UUID.randomUUID().toString().replaceAll("-", "");
		params.put("nonce_str", nonce_str);
		params.put("body", body);
		params.put("detail", detail);
		params.put("attach", attach);
		params.put("out_trade_no", out_trade_no);
		params.put("fee_type", "CNY");
		params.put("total_fee", total_fee);
		params.put("spbill_create_ip", WxConfig.wx_client_ip);
		params.put("time_start", time_start);
		params.put("time_expire", time_expire);
		params.put("notify_url", WxConfig.url_notify_zhajinhua);
		params.put("trade_type", WxConfig.trade_type_jsapi);
		params.put("openid", openid);
		String sign = MicroBlog.sign(params, WxConfig.wx_key);
		String xml = "<xml>";
		Set<String> keyS = params.keySet();
		for (Iterator<String> iterator = keyS.iterator(); iterator.hasNext();) {
			String v = iterator.next();
			xml += "<" + v + ">" + params.get(v) + "</" + v + ">";
		}
		xml += "<sign>" + sign + "</sign>";
		xml += "</xml>";
		return MicroBlog.postHttps(WxConfig.url_unifiedorder, xml, null, null);
	}

	/**
	 * 企业付款
	 * 
	 * @return
	 */
	public static String qiyefukuan(String openId, String reUserName,
			String amount, String desc) {
		Map<String, String> params = new HashMap<String, String>();
		params.put("mch_appid", WxConfig.wx_appid);
		params.put("mchid", WxConfig.wx_mch_id);
		params.put("nonce_str", getRandomNonce_str());
		params.put("partner_trade_no", getRandomMch_billno());
		// 收款用户openid
		params.put("openid", openId);
		if (!StringUtils.isEmpty(reUserName)) {
			// 不实名：NO_CHECK；强制实名：FORCE_CHECK；非强制实名OPTION_CHECK
			params.put("check_name", "FORCE_CHECK");
			// 收款用户姓名，不实名NO_CHECK可不传
			params.put("re_user_name", reUserName);
		} else {
			// 不实名：NO_CHECK；强制实名：FORCE_CHECK；非强制实名OPTION_CHECK
			params.put("check_name", "NO_CHECK");
		}
		// 金额/分
		params.put("amount", amount);
		// 企业付款描述信息
		params.put("desc", desc);
		// 客户端ip
		params.put("spbill_create_ip", WxConfig.wx_client_ip);
		String sign = MicroBlog.sign(params, WxConfig.wx_key);
		String xml = "<xml>";
		Set<String> keyS = params.keySet();
		for (Iterator<String> iterator = keyS.iterator(); iterator.hasNext();) {
			String v = iterator.next();
			xml += "<" + v + ">" + params.get(v) + "</" + v + ">";
		}
		xml += "<sign>" + sign + "</sign>";
		xml += "</xml>";
		return MicroBlog.postHttps(WxConfig.url_qiyefukuan, xml,
				WxConfig.wx_cert, WxConfig.wx_cert_pwd);
	}
}
